<template>
  <div class="app-container" style="height: 100%; padding-left: 5px !important;">
    <div style="border-radius: 2px; float: left; width: 20%; padding-right:10px;height: 100%;overflow: auto">
      <el-input v-model="filterText" placeholder="请输入要搜索的节点" style="margin-bottom:5px;" />
      <el-tree
        ref="tree"
        :data="tree_data"
        :props="defaultProps"
        :highlight-current="true"
        class="filter-tree"
        :default-expanded-keys="[1, 10]"
        :expand-on-click-node="false"
        :filter-node-method="filterNode"
        node-key="id"
        draggable
        :allow-drop="allowDrop"
        @node-drop="node_drop"
        @node-click="node_click"
      >
        <span slot-scope="{ node, data }" class="custom-tree-node" @mouseenter="getcase(data)">
          <span v-if="data.type===0"><i :class="icon0" style="padding-right: 5px" />{{ node.label }}</span>
          <span v-if="data.type===1"><i :class="icon1" style="padding-right: 5px" />{{ node.label }}</span>
          <span v-if="data.type===2"><i :class="icon2" style="padding-right: 5px" />{{ node.label }}</span>
          <span v-if="data.type === 0" class="right" :class="{newStyle: 1 === number}">
            <el-dropdown placement="bottom">
              <i class="el-icon-more" />
              <span class="el-dropdown-link" style="font-size: 20px" />
              <el-dropdown-menu slot="dropdown" class="header-new-drop">
                <el-dropdown-item icon="el-icon-folder-add" @click.native="new_menu(data)">新建子菜单</el-dropdown-item>
              </el-dropdown-menu>
            </el-dropdown>
          </span>
          <span v-if="data.type === 1" class="right" :class="{newStyle: 1 === number}">
            <el-dropdown placement="bottom">
              <i class="el-icon-more" />
              <span class="el-dropdown-link" style="font-size: 20px" />
              <el-dropdown-menu slot="dropdown" class="header-new-drop">
                <el-dropdown-item icon="el-icon-folder-add" @click.native="new_menu(data)">新增</el-dropdown-item>
                <el-dropdown-item divided icon="el-icon-edit" @click.native="edit(data)">重命名</el-dropdown-item>
                <el-dropdown-item divided icon="el-icon-upload" @click.native="input(data)">*.json文件导入</el-dropdown-item>
                <el-dropdown-item divided icon="el-icon-upload2" @click.native="curl_input(data)">curl(bash)命令导入</el-dropdown-item>
                <el-dropdown-item divided icon="el-icon-upload" @click.native="input_case_details(node, data)">Markdown导入接口</el-dropdown-item>
                <el-dropdown-item divided icon="el-icon-folder-delete" @click.native="delete_del(node, data)">删除文件夹</el-dropdown-item>
              </el-dropdown-menu>
            </el-dropdown>
          </span>
          <span v-if="data.type ===2" class="right" :class="{newStyle: 2 === number}">
            <el-dropdown placement="bottom">
              <i class="el-icon-more" />
              <span class="el-dropdown-link" style="font-size: 20px" />
              <el-dropdown-menu slot="dropdown" class="header-new-drop">
                <el-dropdown-item icon="el-icon-edit" @click.native="edit(data)">重命名</el-dropdown-item>
                <el-dropdown-item divided icon="el-icon-document-copy" @click.native="copy(node, data)">复制接口</el-dropdown-item>
                <el-dropdown-item divided icon="el-icon-upload" @click.native="input_case_detail(node, data)">导入接口说明</el-dropdown-item>
                <el-dropdown-item divided icon="el-icon-document-delete" @click.native="delete_case(node, data)">删除接口</el-dropdown-item>
              </el-dropdown-menu>
            </el-dropdown>
          </span>
        </span>
      </el-tree>
    </div>
    <div>
      <el-dialog
        title="新增子菜单"
        :visible.sync="dialogVisible"
        width="30%"
        :before-close="handleClose"
      >
        <el-form :model="menu_pid">
          <el-form-item label="Type：">
            <el-select v-model="type_value">
              <el-option
                v-for="item in type_form"
                :key="item.value"
                :label="item.label"
                :value="item.value"
              />
            </el-select>
          </el-form-item>
          <el-form-item label="菜单名称">
            <el-input v-model="menu_form.label" />
          </el-form-item>
        </el-form>
        <span slot="footer" class="dialog-footer">
          <el-button @click="dialogVisible = false">取 消</el-button>
          <el-button type="primary" @click="add_menu">确 定</el-button>
        </span>
      </el-dialog>
    </div>
    <div>
      <el-dialog
        title="重命名"
        :visible.sync="editdialogVisible"
        width="30%"
        :before-close="handleClose"
      >
        <el-form :model="menu_form">
          <el-form-item label="menu_id">
            <el-input v-model="menu_form.id" readonly />
          </el-form-item>
          <el-form-item label="菜单名称">
            <el-input v-model="re_name" />
          </el-form-item>
        </el-form>
        <span slot="footer" class="dialog-footer">
          <el-button @click="editdialogVisible = false">取 消</el-button>
          <el-button type="primary" @click="edit_menu">确 定</el-button>
        </span>
      </el-dialog>
    </div>
    <el-dialog
      v-if="dialogImport"
      :visible.sync="dialogImport"
      title="导入"
      width="30%"
      append-to-body
    >
      <div style="padding-block-end: 20px; text-align:center">
        <el-radio v-model="radio" label="postman">Postman</el-radio>
        <el-radio v-model="radio" label="yapi">YAPI</el-radio>
        <el-radio v-model="radio" label="eolink">Eolink(开发中，敬请期待)</el-radio>
      </div>
      <div style="text-align:center">
        <!-- 此处action需为有效的任意接口——当前为官网范例接口 -->
        <el-upload
          ref="upload"
          drag
          :limit="1"
          action="https://jsonplaceholder.typicode.com/posts/"
          accept=".json, .xlsx, .xls, .md"
          :file-list="fileList"
          :http-request="md_onSuccess"
          :on-remove="onRemove"
          :headers="{ 'Content-Type': 'application/x-www-form-urlencoded', 'Content-Type': 'multipart/form-data' }"
        >
          <i class="el-icon-upload" />
          <div class="el-upload__text">将文件拖到此处，或<em>点击上传</em></div>
          <div slot="tip" class="el-upload__tip">
            可上传 Postman，YAPI，Eolink 导出的 .json 文件，且只能上传 1 个文件
          </div>
        </el-upload>
      </div>
      <span slot="footer">
        <el-button size="mini" type="danger" @click="dialogImport = false">取 消</el-button>
        <el-button size="mini" type="primary" @click="inputcase">确 定</el-button>
      </span>
    </el-dialog>
    <div>
      <el-dialog
        v-if="markdown_Import"
        :visible.sync="markdown_Import"
        title="导入"
        width="30%"
        append-to-body
      >
        <div style="text-align:center">
          <!-- 此处action需为有效的任意接口——当前为官网范例接口 -->
          <el-upload
            ref="upload"
            drag
            :limit="1"
            action="https://jsonplaceholder.typicode.com/posts/"
            accept=".md"
            :file-list="fileList"
            :on-remove="onRemove"
            :http-request="md_onSuccess"
            :headers="{ 'Content-Type': 'application/x-www-form-urlencoded', 'Content-Type': 'multipart/form-data', 'Access-Control-Allow-Origin': '*' }"
          >
            <i class="el-icon-upload" />
            <div class="el-upload__text">将文件拖到此处，或<em>点击上传</em></div>
            <div slot="tip" class="el-upload__tip">
              可上传 git 导出的 .md 文件，且只能上传 1 个文件
            </div>
          </el-upload>
        </div>
        <span slot="footer">
          <el-button size="mini" type="danger" @click="markdown_Import = false">取 消</el-button>
          <el-button size="mini" type="primary" @click="input_detail">确 定</el-button>
        </span>
      </el-dialog>
    </div>
    <div>
      <el-dialog
        v-if="markdown_type1_Import"
        :visible.sync="markdown_type1_Import"
        title="导入"
        width="30%"
        append-to-body
      >
        <div style="text-align:center">
          <!-- 此处action需为有效的任意接口——当前为官网范例接口 -->
          <el-upload
            ref="upload"
            drag
            :limit="1"
            action="https://jsonplaceholder.typicode.com/posts/"
            accept=".md"
            :file-list="fileList"
            :on-remove="onRemove"
            :http-request="md_onSuccess"
            :headers="{ 'Content-Type': 'application/x-www-form-urlencoded', 'Content-Type': 'multipart/form-data', 'Access-Control-Allow-Origin': '*' }"
          >
            <i class="el-icon-upload" />
            <div class="el-upload__text">将文件·到此处，或<em>点击上传</em></div>
            <div slot="tip" class="el-upload__tip">
              可上传 git 导出的 .md 文件，且只能上传 1 个文件
            </div>
          </el-upload>
        </div>
        <span slot="footer">
          <el-button size="mini" type="danger" @click="markdown_type1_Import = false">取 消</el-button>
          <el-button size="mini" type="primary" @click="input_detail_type2">确 定</el-button>
        </span>
      </el-dialog>
    </div>
    <div>
      <el-dialog
        title="提示"
        :visible.sync="del_case_dialog"
        width="20%"
      >
        <span>是否删除改配置项</span>
        <span slot="footer" class="dialog-footer">
          <el-button @click="del_case_dialog = false">取 消</el-button>
          <el-button type="primary" @click="deletepro()">确 定</el-button>
        </span>
      </el-dialog>
    </div>
    <el-dialog
      v-if="curl_dialogImport"
      :visible.sync="curl_dialogImport"
      title="填写CURL"
      width="40%"
      append-to-body
    >
      <div style="height: 500px; width: 700px">
        <textarea v-model="curl_data" style="height: 100%; width: 100%" />
      </div>
      <span slot="footer">
        <el-button size="mini" type="danger" @click="curl_dialogImport = false">取 消</el-button>
        <el-button size="mini" type="primary" @click="input_curl">确 定</el-button>
      </span>
    </el-dialog>
    <div style="overflow: auto; height: 100%">
      <el-tabs v-model="TabsValue" type="card" closable @tab-remove="removeTab" @tab-click="tab_click">
        <el-tab-pane
          v-for="(item) in tableTabs"
          :key="item.name"
          :label="item.title"
          :name="item.name"
        >
          <span slot="label">
            <span v-if="item.type===1"><i :class="icon1" style="padding-right: 5px" />{{ item.title }}</span>
            <span v-if="item.type===2"><i :class="icon2" style="padding-right: 5px" />{{ item.title }}</span>
          </span>
          <div v-show="1 === number">
            <el-container>
              <Case_list v-if="update" :table="table_data" :tree="tree_data" style="float:left; width:100%; padding-top: 0" />
            </el-container>
          </div>
          <div v-show="2 === number">
            <el-container>
              <Case_info v-if="update" :form="form_case" style="float:left; width:100%; padding-top: 0" />
            </el-container>
          </div>
        </el-tab-pane>
      </el-tabs>
    </div>
  </div>
</template>

<script>
import {
  addmenu,
  change_pid,
  copy_case,
  curl_input_case,
  deletecase,
  deletepeoject,
  getallTestcase,
  getCase_tree,
  getsinglecase,
  getsingleTestcaselist,
  upload_case_detail,
  uploadcase
} from "@/api/testcase";
import case_info from "./case_info";
import case_list from "./case_list";

export default {
  name: 'CaseIndex',
  components: {
    "Case_info": case_info,
    "Case_list": case_list
  },
  props: {
    // eslint-disable-next-line vue/prop-name-casing,vue/require-default-prop,vue/require-prop-type-constructor
    table_current_page: 1
  },
  data() {
    return {
      view_result_dialog: true,
      markdown_type1_Import: false,
      markdown_Import: false,
      tableTabs: [],
      del_case_dialog: false,
      re_name: "",
      radio: "postman",
      uploadData: [],
      fileList: [],
      dialogImport: false,
      editableTabsValue: '根目录',
      tree_name: '',
      editableTabs: [],
      tabIndex: 2,
      case_page: {
        current_page: 1,
        size_page: 10,
      },
      node_data: {},
      list: null,
      number: 1,
      filterText: '',
      listLoading: true,
      curl_dialogImport: false,
      input_type: false,
      inputValue: '',
      menu_pid: null,
      update: true,
      icon0: 'el-icon-s-home',
      icon1: 'el-icon-folder-opened',
      icon2: 'el-icon-document',
      // 列表
      table_data: [], // 目录
      defaultProps: {
        children: 'children',
        label: 'label',
        id: "id"
      },
      tree_data: [],
      type_value: '',
      pid_list: [],
      tree_menu_id: null,
      type_form: [
        {
          label: "文件夹",
          value: 1
        },
        {
          label: "接口",
          value: 2
        },
      ],
      curl_data: "",
      // 菜单
      m_id: null,
      menu_form: {
        label: '',
        pid: '',
        type: null,
        user_id: null,
      },
      // 用例id
      case_form: {
        menu_id: '',
        current_page: 1,
        size_page: 3,
      },
      TabsValue: "",
      // 用例详情
      form_case:
        {
          assert_form: [
            {
              assert_key: '',
              assert_value: ''
            }
          ],
          params: [{ key: '', value: '' }],
          extract: []
        },
      params_form: {},
      editdialogVisible: false,
      dialogVisible: false,
      pidFrom: {
        id: null
      },
    }
  },
  watch: {
    filterText(val) {
      this.$refs.tree.filter(val);
    }
  },
  created() {
    this.get_tree()
    this.getall()
    this.is_login()
  },
  methods: {
    is_login() {
      const user_id = localStorage.getItem("user_id");
      if (!user_id) {
        this.$router.push("/login");
        this.$message.error("未登录，请前往登录");
      }
    },
    input_detail_type2() {
      const req = {}
      req.id = this.pid_list.id
      req.type = 1
      req.detail = this.uploadData
      req.user_id = Number(localStorage.getItem("user_id"))
      upload_case_detail(req).then(res => {
        if (res.data.code === 200) {
          this.$message({
            type: "success",
            message: res.data.message,
          })
          this.markdown_type1_Import = false
          this.form_case.detail = res.data.detail
          for (const item of res.data.data) {
            this.pid_list.children.push(item)
          }
        } else {
          this.$message({
            type: "error",
            message: res.data.message,
          })
        }
      })
    },
    md_onSuccess(o) {
      const reader = new FileReader()
      reader.readAsText(o.file)
      reader.onload = (e) => {
        this.uploadData = e.target.result
      }
    },
    input_detail() {
      const req = {}
      req.id = this.pid_list.id
      req.type = 2
      req.detail = this.uploadData
      req.user_id = Number(localStorage.getItem("user_id"))
      upload_case_detail(req).then(res => {
        if (res.data.code === 200) {
          this.$message({
            type: "success",
            message: res.data.message,
          })
          this.markdown_Import = false
          this.form_case.detail = res.data.detail
        } else {
          this.$message({
            type: "error",
            message: res.data.message,
          })
        }
      })
    },
    input_case_details(node, data) {
      this.markdown_type1_Import = true
      this.pid_list = data
      if (this.children_view(this.pid_list) === 0) {
        this.pid_list.children = []
      }
    },
    input_case_detail(node, data) {
      this.markdown_Import = true
      this.pid_list = data
      if (this.children_view(this.pid_list) === 0) {
        this.pid_list.children = []
      }
    },
    allowDrop(from, to, type) {
      return !(to.data.type === 2 || type !== 'inner');
    },
    node_drop(from, to) {
      const req = {}
      req.from_id = from.data.id
      req.to_id = to.data.id
      change_pid(req).then(res => {
        if (res.data.code === 200) {
          this.$message.success(res.data.message)
        } else if (res.data.code !== 200) {
          this.$message.error(res.data.message)
        }
      })
    },
    filterNode(value, tree_data) {
      if (!value) return true;
      return tree_data.label.indexOf(value) !== -1;
    },
    // 导入文件
    input(data) {
      this.dialogImport = true
      this.pid_list = data
    },
    // 移除文件
    onRemove(file) {
      this.fileList = [];
    },
    // 导入确认
    inputcase() {
      this.$confirm("导入后原数据会被覆盖，确定导入吗?", "温馨提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning", }).then(() => {
        // 使用目标数据变量接收上传后的文件数据
        const req = {}
        req.user_id = Number(localStorage.getItem("user_id"))
        req.pid = this.pid_list.id
        req.upload_type = this.radio
        req.content = this.uploadData
        uploadcase(req).then(res => {
          if (res.data.code === 200) {
            this.$message({
              type: "success",
              message: "导入成功!",
            })
            this.dialogImport = false
            for (const item of res.data.result) {
              this.pid_list.children.push(item)
            }
          } else if (res.data.code !== 200) {
            this.$message({
              type: "error",
              message: "导入失败!",
            })
          }
        })
      })
    },
    children_view(data) {
      if ("children" in data) { // json就是数组，name是你要找的值
        return 1
      } else {
        return 0
      }
    },
    // curl_input导入
    curl_input(data) {
      this.curl_dialogImport = true
      this.curl_data = ""
      this.pid_list = data
      const list = []
      if (this.children_view(this.pid_list) === 0) {
        this.pid_list.children = list
      }
      console.log(this.pid_list)
    },
    input_curl() {
      const req = {}
      req.user_id = Number(localStorage.getItem("user_id"))
      req.menu_id = this.pid_list.id
      req.curl_data = this.curl_data
      curl_input_case(req).then(res => {
        if (res.data.code === 200) {
          this.$message.success(res.data.message)
          this.pid_list.children.push(res.data.data)
          this.curl_dialogImport = false
        } else if (res.data.code !== 200) {
          this.$message.error(res.data.message)
        }
      })
    },
    // 刷新组件
    reload() {
      this.update = false
      this.$nextTick(() => (this.update = true))
    },
    // 获取接口目录
    get_tree() {
      getCase_tree().then(res => {
        this.tree_data = res.data.content
      })
    },
    // 获取所有测试用例
    getall() {
      getallTestcase().then(res => {
        this.table_data = res.data.content
      })
    },
    // 获取单个文件夹列表
    getsinglelist() {
      const req = this.pidFrom
      req.current_page = 1
      req.size_page = 8
      getsingleTestcaselist(req).then(res => {
        this.table_data = res.data
      })
    },
    // 获取接口详情
    get_single_case(data) {
      getsinglecase(data).then(res => {
        // 详细内容
        this.form_case = res.data
        this.form_case.headers = res.data.headers
      })
    },
    // 复制接口
    copy(node, data) {
      this.pid_list = node.parent
      const req = this.menu_form
      req.id = data.id
      req.label = data.label
      req.pid = data.pid
      req.type = 2
      req.user_id = Number(localStorage.getItem("user_id"))
      copy_case(this.menu_form).then(res => {
        if (res.data.code === 200) {
          this.$message.success(res.data.message)
          this.pid_list.data.children.push(res.data.data)
        } else if (res.data.code === 100) {
          this.$message.error("必要参数不可为空")
        }
      })
    },
    delete_case(node, data) {
      deletecase({ "menu_id": data.id }).then(res => {
        if (res.data.code === 200) {
          this.$message({
            message: "删除接口成功",
            type: "success"
          })
          const parent = node.parent;
          const children = parent.data.children || parent.data;
          const index = children.findIndex(d => d.id === data.id);
          children.splice(index, 1);
        } else if (res.data.code === 100) {
          this.$message({
            message: "删除接口失败，无此接口",
            type: 'error'
          })
        }
      })
    },
    delete_del(node, data) {
      this.del_case_dialog = true
      this.node_data = node
      this.pid_list = data
    },
    // 删除文件夹
    deletepro() {
      const data = this.pid_list
      const node = this.node_data
      deletepeoject({ "id": data.id }).then(res => {
        if (res.data.code === 200) {
          this.$message({
            message: res.data.message,
            type: "success"
          })
          const parent = node.parent;
          const children = parent.data.children || parent.data;
          const index = children.findIndex(d => d.id === data.id);
          children.splice(index, 1);
          this.del_case_dialog = false
        } else {
          this.$message({
            message: res.data.message,
            type: 'error'
          })
        }
      })
    },
    tab_click(tab) {
      const tabs = this.tableTabs
      for (const t of tabs) {
        if (t.name === tab.name) {
          if (t.type === 1) {
            this.number = 1
            this.pidFrom.id = t.content
            this.getsinglelist()
          } else if (t.type === 2) {
            this.number = 2
            this.get_single_case({
              "menu_id": t.content,
              "current_page": 1,
              "size_page": 3
            })
          }
        }
      }
    },
    removeTab(targetName) {
      const tabs = this.tableTabs;
      let activeName = this.TabsValue;
      if (activeName === targetName) {
        tabs.forEach((tab, index) => {
          if (tab.name === targetName) {
            const nextTab = tabs[index + 1] || tabs[index - 1];
            if (nextTab) {
              activeName = nextTab.name;
              this.tab_click(nextTab)
            }
          }
        });
      }
      this.TabsValue = activeName;
      this.tableTabs = tabs.filter(tab => tab.name !== targetName);
    },
    addTab(targetName, id, type) {
      const index = this.tableTabs.findIndex(item => item.title === targetName)
      if (index === -1) {
        this.tableTabs.push({
          title: targetName,
          name: targetName,
          content: id,
          type: type
        })
      }
      this.TabsValue = targetName;
    },
    node_click(data) {
      if (data.type === 1) {
        this.addTab(data.label, data.id, data.type)
        this.number = 1
        this.menu_pid = data.id
        this.pidFrom.id = data.id
        this.m_id = data.pid
        this.tree_name = data.label
        this.getsinglelist()
      } else if (data.type === 2) {
        this.addTab(data.label, data.id, data.type)
        this.number = 2
        this.case_form.menu_id = data.id
        this.pidFrom.id = data.id
        this.tree_name = data.label
        this.m_id = data.pid
        this.menu_pid = data.id
        this.get_single_case({
          "menu_id": data.id,
          "current_page": 1,
          "size_page": 3
        })
      }
    },
    getcase(data) {
      switch (data.type) {
        case 1:
          this.menu_pid = this.pidFrom.id = data.id;
          this.m_id = data.pid;
          break;
        case 2:
          this.case_form.menu_id = this.menu_pid = this.pidFrom.id = data.id;
          this.m_id = data.pid;
          break;
        case 0:
          this.menu_pid = this.pidFrom.id = data.id;
          break;
        default:
          // handle unexpected data.type
          break;
      }
    },
    new_menu(data) {
      this.dialogVisible = true
      this.pid_list = data
      this.tree_menu_id = data.id
      if (this.children_view(this.pid_list) === 0) {
        this.pid_list.children = []
      }
    },
    add_menu() {
      const req = this.menu_form
      req.type = this.type_value
      req.pid = this.tree_menu_id
      req.user_id = Number(localStorage.getItem("user_id"))
      addmenu(this.menu_form).then(res => {
        if (res.data.code === 200) {
          this.$message({
            message: res.data.message,
            type: 'success'
          })
          this.dialogVisible = false
          this.pid_list.children.push(res.data.data)
        } else if (res.data.code === 100) {
          this.dialogVisible = true
          this.$message.error("菜单名称不可为空")
        } else if (res.data.code === 101) {
          this.dialogVisible = true
          this.$message.error("名称已存在，请重新输入")
        }
      })
    },
    edit(data) {
      this.menu_form.id = data.id
      this.editdialogVisible = true
      this.pid_list = data
    },
    edit_menu() {
      const req = this.menu_form
      req.id = this.menu_form.id
      req.label = this.re_name
      req.pid = this.pid_list.id
      req.user_id = Number(localStorage.getItem("user_id"))
      addmenu(req).then(res => {
        if (res.data.code === 200) {
          this.$message({
            message: '重命名成功',
            type: 'success'
          })
          this.editdialogVisible = false
          const temp = this.tableTabs.find(o => o.content === this.menu_form.id)
          if (temp) {
            temp.title = res.data.label;
          }
          this.pid_list.label = res.data.label
          this.form_case.name = res.data.label
        } else if (res.data.code === 100) {
          this.editdialogVisible = true
          this.$message.error("菜单名称不可为空")
        } else if (res.data.code === 101) {
          this.editdialogVisible = true
          this.$message.error("名称已存在，请重新输入")
        }
      })
    },
    handleClose(done) {
      done()
    },
  }
}
</script>

<style scoped>
  .el-button{
    padding: 4px;
  }
  .custom-tree-node {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: space-between;
    font-size: 14px;
    padding-right: 4px;
  }
  .el-dropdown {
    font-size: 16px;
    color: #5d697a;
  }
</style>
